package mq;

import java.util.HashMap;
import java.util.Map;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;

/**
 * Uses protostuff to serialize.
 * 
 * @author zhuyuanbiao
 *
 * @date 2018年1月24日 下午4:53:22
 */
public class ProtostuffSerializer implements Serializer {

	private volatile Map<Class<?>, Schema<?>> schemas = new HashMap<>();

	private <T> Schema<T> getSchema(Class<T> clazz) {
		Schema<T> schema = (Schema<T>) schemas.get(clazz);
		synchronized (this) {
			if (schema == null) {
				schema = RuntimeSchema.getSchema(clazz);
				schemas.put(clazz, schema);
			}
		}
		return schema;
	}

	@Override
	public byte[] serialize(Object obj) {
		Class<?> clazz = obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema schema = getSchema(clazz);
            return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            buffer.clear();
        }
	}

	@Override
	public <T> T deserialize(byte[] data, Class<T> clazz) {
		try {
			T result = clazz.newInstance();
            Schema schema = getSchema(clazz);
            ProtostuffIOUtil.mergeFrom(data, result, schema);
            return result;
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
	}

}
